package scu.maqiang.mesh;

import java.io.FileWriter;
import java.io.IOException;
import java.util.HashSet;

import scu.maqiang.numeric.Constants;
import scu.maqiang.numeric.MVO;
import scu.maqiang.numeric.UnorderIntArray;

public class Mesh2Q9 extends Mesh {

    public Mesh2Q9() {
        super();
        nDim = 2;
        nPerElement = 9;
        nPerBoundary = 3;
        nBoundaryPerElement = 4;
        nEdgePerElement = 8;
        nEdgePerBoundary = 2;
        tecplotType = "FEQUADRILATERAL";
    }

    public Mesh2Q9 square2D(int xNum, int yNum) {
        int i, j, li, lj, lk;
        int[] t = new int[9];
        int nv = (2 * xNum + 1) * (2 * yNum + 1);
        int nt = xNum * yNum;
        int nb = 2 * (xNum + yNum);
        initMesh0(nv, nt, nb);
        int count  = 0;
        for(j = 0; j < 2 * yNum + 1; j++) {
            for(i = 0; i < 2 * xNum + 1; i++) {
                nodes[count++] = new double[] {i / (2.0 * xNum), 1.0 * j / (2 * yNum)};
            }
        }

        count = 0;
        for(j = 0; j < yNum; j++) {
            for(i = 0; i < xNum; i++) {
                t[0] = 2 * j * (2 * xNum + 1) + 2 * i;
                t[1] = t[0] + 2;
                t[2] = t[1] + 2 * (2 * xNum + 1);
                t[3] = t[0] + 2 * (2 * xNum + 1);
                t[4] = t[0] + 1;
                t[5] = t[1] + 2 * xNum + 1;
                t[6] = t[2] - 1;
                t[7] = t[0] + 2 * xNum + 1;
                t[8] = t[7] + 1;
                elements[count++] = t.clone();
            }
        }

        count = 0;
        for(i = 0; i < xNum; i++) {
            li = 2 * i;
            lj = li + 2;
            lk = li + 1;
            boundaries[count] = new int[] {li, lj, lk};
            boundaryLabel[count++]  = 1;
        }

        for(i = 0; i < yNum; i++) {
            li = i * (4 * xNum + 2) + 2 * xNum;
            lj = li + 4 * xNum + 2;
            lk = li + 2 * xNum + 1;
            boundaries[count] = new int[] {li, lj, lk};
            boundaryLabel[count++] = 2;
        }

        for(i = 0; i < xNum; i++) {
            li = nv - 1 - 2 * i;
            lj = li - 2;
            lk = li - 1;
            boundaries[count] = new int[] {li, lj, lk};
            boundaryLabel[count++] = 3;
        }

        for(i = 0; i < yNum; i++) {
            li = i * (4 * xNum + 2);
            lj = li + 4 * xNum + 2;
            lk = li + 2 * xNum + 1;
            boundaries[count] = new int[] {lj, li, lk};
            boundaryLabel[count++] =  4;
        }
        return this;
    }

    @Override
    public double[] getinteriorPointInElement(double[][] coord) {
        return coord[8].clone();
    }

    @Override
    public double[] getinteriorPointOnBoundary(double[][] coord) {
        return coord[2].clone();
    }

    @Override
    public int[][] getBoundarysFromElement(int i) {
        int[][] boundarys = new int[nBoundaryPerElement][];
        int[] ele = elements[i];
        boundarys[0] = new int[] {ele[0], ele[1], ele[4]};
        boundarys[1] = new int[] {ele[1], ele[2], ele[5]};
        boundarys[2] = new int[] {ele[2], ele[3], ele[6]};
        boundarys[3] = new int[] {ele[3], ele[0], ele[7]};
        return boundarys;
    }

    @Override
    public boolean checkMesh(double[][] coord) {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public int getTecplotNt() {
        // TODO Auto-generated method stub
        return nt;
    }

    public int[][] getEdgesFromElement(int i) {
        int[][] result = new int[8][];
        int[] ele = elements[i];
        result[0] = new int[] {ele[0], ele[4]};
        result[1] = new int[] {ele[4], ele[1]};
        result[2] = new int[] {ele[1], ele[5]};
        result[3] = new int[] {ele[5], ele[2]};
        result[4] = new int[] {ele[2], ele[6]};
        result[5] = new int[] {ele[6], ele[3]};
        result[6] = new int[] {ele[3], ele[7]};
        result[7] = new int[] {ele[7], ele[0]};
        return result;
    }

	@Override
	public void toTecplot(String fileName) {
		try (FileWriter fw = new FileWriter(fileName)){
			fw.write(Tecplot.meshFileString + "\n");
			fw.write(Tecplot.dimVariableString[nDim - 1] + "\n");
			fw.write("ZONE NODES=" + nv + ", ELEMENTS=" + nt * 4 + ", DATAPACKING=POINT, ZONETYPE=" + tecplotType +"\n");
            for (int i = 0; i < nv; i++) {
                for (int j = 0; j < nDim; j++) {
                    fw.write(nodes[i][j] + "\t");
                }
                fw.write("\n");
            }
			for(int i = 0; i < nt; i++) {
			    int[] ele = elements[i];
			    fw.write((ele[0] + 1) + "\t " + (ele[4] + 1) + "\t " + (ele[8] + 1) + "\t " + (ele[7] + 1) + "\n");
                fw.write((ele[4] + 1) + "\t " + (ele[1] + 1) + "\t " + (ele[5] + 1) + "\t " + (ele[8] + 1) + "\n");
                fw.write((ele[7] + 1) + "\t " + (ele[8] + 1) + "\t " + (ele[6] + 1) + "\t " + (ele[3] + 1) + "\n");
                fw.write((ele[8] + 1) + "\t " + (ele[5] + 1) + "\t " + (ele[2] + 1) + "\t " + (ele[6] + 1) + "\n");
            }
			fw.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
    @Override
    public void toTecplot(String fileName, double[] x) {
        try (FileWriter fw = new FileWriter(fileName)){
            fw.write(Tecplot.meshFileString + "\n");
            fw.write(Tecplot.dimVariableString[nDim - 1] + ", u\n");
            fw.write("ZONE NODES=" + nv + ", ELEMENTS=" + nt * 4 + ", DATAPACKING=POINT, ZONETYPE=" + tecplotType +"\n");
            for (int i = 0; i < nv; i++) {
                for (int j = 0; j < nDim; j++) {
                    fw.write(nodes[i][j] + "\t ");
                }
                fw.write(x[i] + "\n");
            }
            for(int i = 0; i < nt; i++) {
                int[] ele = elements[i];
                fw.write((ele[0] + 1) + "\t " + (ele[4] + 1) + "\t " + (ele[8] + 1) + "\t " + (ele[7] + 1) + "\n");
                fw.write((ele[4] + 1) + "\t " + (ele[1] + 1) + "\t " + (ele[5] + 1) + "\t " + (ele[8] + 1) + "\n");
                fw.write((ele[7] + 1) + "\t " + (ele[8] + 1) + "\t " + (ele[6] + 1) + "\t " + (ele[3] + 1) + "\n");
                fw.write((ele[8] + 1) + "\t " + (ele[5] + 1) + "\t " + (ele[2] + 1) + "\t " + (ele[6] + 1) + "\n");
            }
            fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void toTecplot(String fileName, double[][] mat) {
        int col = mat.length;
        try (FileWriter fw = new FileWriter(fileName)){
            fw.write(Tecplot.meshFileString + "\n");
            fw.write(Tecplot.dimVariableString[nDim - 1]);
            for (int i = 0; i < col; i++) {
                fw.write(", \"u" + (i + 1) + "\"");
            }
            fw.write("\n");
            fw.write("ZONE NODES=" + nv + ", ELEMENTS=" + nt * 4 + ", DATAPACKING=POINT, ZONETYPE=" + tecplotType +"\n");
            for (int i = 0; i < nv; i++) {
                for (int j = 0; j < nDim; j++) {
                    fw.write(nodes[i][j] + "\t ");
                }
                for (int j = 0; j < col; j++) {
                    fw.write(mat[j][i] + "\t ");
                }
                fw.write("\n");
            }
            for(int i = 0; i < nt; i++) {
                int[] ele = elements[i];
                fw.write((ele[0] + 1) + "\t " + (ele[4] + 1) + "\t " + (ele[8] + 1) + "\t " + (ele[7] + 1) + "\n");
                fw.write((ele[4] + 1) + "\t " + (ele[1] + 1) + "\t " + (ele[5] + 1) + "\t " + (ele[8] + 1) + "\n");
                fw.write((ele[7] + 1) + "\t " + (ele[8] + 1) + "\t " + (ele[6] + 1) + "\t " + (ele[3] + 1) + "\n");
                fw.write((ele[8] + 1) + "\t " + (ele[5] + 1) + "\t " + (ele[2] + 1) + "\t " + (ele[6] + 1) + "\n");
            }
            fw.write("\n");
            fw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
//
//	@Override
//	public void toTecplot(String fileName, double[][] mat) {
//		int row = mat.length;
//		int j = 0;
//		try (FileWriter fw = new FileWriter(fileName)){
//			fw.write("title = solution file\n");
//			fw.write("variables= \"x\", \"y\"");
//			for(int i = 0; i < row; i++) {
//				fw.write(", \"u" + (i + 1) + "\"");
//			}
//			fw.write("\n");
//
//			fw.write(Tecplot.ZoneString(this) + "\n");
//			for (Node node : nodes) {
//				fw.write(node + "\t");
//				for(int i = 0; i < row; i++) {
//					fw.write(mat[i][j] + "\t");
//				}
//				j++;
//				fw.write("\n");
//			}
//
//			writeElements(fw);
//			fw.flush();
//			fw.close();
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
//	}
//
//	@Override
//	public void toTecplot(String fileName, double time, double[] x) {
//		try (FileWriter fw = new FileWriter(fileName)){
//			if (Math.abs(time) < Constants.Er) {
//				fw.write("title = solution file\n");
//				fw.write("variables= \"x\", \"y\", \"u\"\n");
//				fw.write(Tecplot.ZoneStringTime(this) + time + "\n");
//				int i = 0;
//				for (Node node : nodes) {
//					fw.write(node + "\t" + x[i++] + "\n");
//				}
//
//				writeElements(fw);
//				fw.flush();
//				fw.close();
//			} else {
//				fw.write(Tecplot.ZoneStringShareTime(this) + time + "\n");
//				for (double xx : x) {
//					fw.write(xx + "\n");
//				}
//				fw.flush();
//				fw.close();
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//	}
//
//	@Override
//	public void toTecplot(String fileName, double time, double[][] mat) {
//		int row = mat.length;
//		try (FileWriter fw = new FileWriter(fileName)){
//			if (Math.abs(time) < Constants.Er) {
//				fw.write("title = mesh file\n");
//				fw.write("variables= \"x\", \"y\"");
//				for(int j = 0; j < row; j++) {
//					fw.write(", \"u" + (j + 1) + "\"");
//				}
//				fw.write("\n");
//
//				fw.write(Tecplot.ZoneString(this) + time + "\n");
//				int j = 0;
//				for (Node node : nodes) {
//					fw.write(node + "\t");
//					for (int i = 0; i < row; i++) {
//						fw.write(mat[i][j] + "\t");
//					}
//					j++;
//					fw.write("\n");
//				}
//
//
//				writeElements(fw);
//				fw.flush();
//				fw.close();
//			} else {
//				fw.write(Tecplot.ZoneStringShareTime(this) + time + "\n");
//				int col = mat[0].length;
//				for(int i = 0; i < row; i++) {
//					for(int j = 0; j < col; j++) {
//						fw.write(mat[i][j] + "\t");
//					}
//					fw.write("\n");
//				}
//				fw.flush();
//				fw.close();
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//	}
//
//	private void writeElements(FileWriter fw) throws IOException{
//		for (Element tri : elements) {
//			int[] idx = tri.idx;
//			fw.write((idx[0] + 1) + "\t" + (idx[1] + 1) + "\t" + (idx[2] + 1) + "\t" + (idx[3] + 1) + "\n");
//		}
//	}

}

